package de.uni_bremen.exceptions.oops;

class ExceptionClassDeclaration extends ClassDeclaration
{
	static final Statement	divisionByZeroExceptionCall;
	
	static final Statement	nullDeRefExceptionCall;
	
	static
	{
		VarOrCall print = new VarOrCall(new ResolvableIdentifier("Print", null));
		print.params.add(new LiteralExpression(101, ClassDeclaration.intType, null));
		divisionByZeroExceptionCall = new CallStatement(new AccessExpression(new NewExpression(
				new ResolvableIdentifier("Exception", null), null), print));
		
		print = new VarOrCall(new ResolvableIdentifier("Print", null));
		print.params.add(new LiteralExpression(102, ClassDeclaration.intType, null));
		nullDeRefExceptionCall = new CallStatement(new AccessExpression(new NewExpression(new ResolvableIdentifier(
				"Exception", null), null), print));
	}
	
	class PrintMethod extends MethodDeclaration
	{
		PrintMethod()
		{
			super(new Identifier("Print", null));
			
			VarDeclaration param = new VarDeclaration(new Identifier("code", null), false, true);
			param.type = new ResolvableIdentifier("Integer", null);
			params.add(param);
			
			// Exception:
			int[] signs = new int[] { 69, 120, 99, 101, 112, 116, 105, 111, 110, 58, 32 };
			
			for (int s : signs)
				statements.add(new WriteStatement(new LiteralExpression(s, ClassDeclaration.intType, null)));
			
			// Division by Zero
			signs = new int[] { 68, 105, 118, 105, 115, 105, 111, 110, 32, 98, 121, 32, 90, 101, 114, 111 };
			IfStatement zeroDivisionIf = new IfStatement(new BinaryExpression(new VarOrCall(new ResolvableIdentifier(
					"code", null)), Symbol.Id.EQ, new LiteralExpression(101, ClassDeclaration.intType, null)));
			for (int s : signs)
				zeroDivisionIf.thenStatements.add(new WriteStatement(new LiteralExpression(s, ClassDeclaration.intType,
						null)));
			
			// DeRef of NULL-value
			signs = new int[] { 68, 101, 82, 101, 102, 32, 111, 102, 32, 78, 85, 76, 76, 45, 118, 97, 108, 117, 101 };
			ElseIfStatement deRefOfNullIf = new ElseIfStatement(new BinaryExpression(new VarOrCall(
					new ResolvableIdentifier("code", null)), Symbol.Id.EQ, new LiteralExpression(102,
					ClassDeclaration.intType, null)));
			for (int s : signs)
				deRefOfNullIf.thenStatements.add(new WriteStatement(new LiteralExpression(s, ClassDeclaration.intType,
						null)));
			zeroDivisionIf.elseIfStatement = deRefOfNullIf;
			
			// Unknown exception
			signs = new int[] { 85, 110, 107, 110, 111, 119, 110, 32, 82, 117, 110, 116, 105, 109, 101, 69, 120, 99,
					101, 112, 116, 105, 111, 110 };
			for (int s : signs)
				deRefOfNullIf.elseStatements.add(new WriteStatement(new LiteralExpression(s, ClassDeclaration.intType,
						null)));
			
			statements.add(zeroDivisionIf);
		}
	}
	
	PrintMethod	printMethod;
	
	ExceptionClassDeclaration()
	{
		super(new Identifier("Exception", null));
		
		methods.put((printMethod = new PrintMethod()), AccessModificator.PUBLIC);
	}
	
	static void contextAnalysisExceptionCalls(Declarations declarations) throws CompileException
	{
		divisionByZeroExceptionCall.contextAnalysis(declarations);
		nullDeRefExceptionCall.contextAnalysis(declarations);
	}
}
